home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
scope
/
151-175
/
scopedisk170
/
pcx2iff
/
pcxtoiff.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-19
|
8KB
|
327 lines
/* PCXtoIFF.c - Converts IBM .PCX picture files to IFF format
*
* Written by David Godshall
* Released into the Public Domain by David Godshall
*
* This little utility was written as the request of another BBS caller who
* wanted to be able to view IBM .PCX type graphic files on his Amiga. He
* uploaded the source to an IBM .PCX viewer which I used to determine the
* format of PCX files in order to be able to write this. I was going to
* write a PCX viewer, but decided it would be better to be able to convert
* PCX files to IFF so more could be done with them then just viewing.
*/
#include <exec/types.h>
#include <stdio.h>
#include <string.h>
#define COMPRESS 1 /* Remove this line to disable compression */
typedef struct {
UBYTE red, green, blue;
} TRIPLET;
typedef struct { /* 128 byte header in PCX files */
UBYTE maker; /* ??? */
UBYTE version; /* PCX version */
UBYTE code; /* ??? */
UBYTE bpp; /* ??? */
WORD x1,y1; /* Top, Left corner */
WORD x2,y2; /* Bottom, Right corner */
WORD hres, vres; /* Dots-Per-Inch */
TRIPLET triple[16]; /* palette */
UBYTE vmode; /* ??? */
UBYTE nplanes; /* Number of bitplanes */
UWORD bpl; /* Number of bytes per row */
UBYTE pad[128-68];
} PCXHDR;
UBYTE Buffer[1024];
int WriteSize,BodyPosition,BodySize;
PCXHDR PCXHeader;
int PCXWide,PCXHigh,PCXDeep,PCX_BPL,IFF_BPL;
#define SwapWord(x) ((x) = ((x) & 0x00FF)<<8 | ((x) & 0xFF00)>>8)
UBYTE ReadByte(fin)
FILE *fin;
{
UBYTE data;
if (fread((char *)&data,1,1,fin) != 1)
{
printf ("%% Error reading PCX file\n");
exit(20);
}
return data;
}
void WriteLong(fout,data)
FILE *fout;
ULONG data;
{
if (fwrite((char *)&data,4,1,fout) != 1)
{
printf ("%% Error writing IFF file\n");
exit(20);
}
WriteSize += 4;
}
void WriteWord(fout,data)
FILE *fout;
UWORD data;
{
if (fwrite((char *)&data,2,1,fout) != 1)
{
printf ("%% Error writing IFF file\n");
exit(20);
}
WriteSize += 2;
}
void WriteByte(fout,data)
FILE *fout;
UBYTE data;
{
if (fwrite((char *)&data,1,1,fout) != 1)
{
printf ("%% Error writing IFF file\n");
exit(20);
}
WriteSize += 1;
}
void WriteData(fout,data,size)
FILE *fout;
APTR data;
int size;
{
if (fwrite((char *)data,size,1,fout) != 1)
{
printf ("%% Error writing IFF file\n");
exit(20);
}
WriteSize += size;
}
void WriteIFFRow(fout,data,size)
FILE *fout;
UBYTE *data;
int size;
{
#ifdef COMPRESS
UBYTE *ptr,*maxptr;
UBYTE ob,b;
int len,pos;
pos = WriteSize;
ptr = data;
maxptr = data+size;
ob = *ptr++;
while (data < maxptr)
{
b = *ptr++;
while (b == ob && ptr < maxptr)
b = *ptr++;
len = ptr - data;
if (ptr < maxptr)
len--;
while (len >= 128)
{
WriteByte(fout,257-128);
WriteByte(fout,ob);
len -= 128;
data += 128;
}
if (len > 2)
{
WriteByte(fout,257-len);
WriteByte(fout,ob);
data += len;
}
else
{
ob = *data;
while (ptr < maxptr)
{
if (b != ob)
{
ob = b;
b = *ptr++;
}
else
if (ptr+1 < maxptr)
{
if (*ptr == b)
break;
ob = b;
b = *ptr++;
}
else
break;
}
len = ptr-data-1;
if (ptr < maxptr)
len--;
while (len > 128)
{
WriteByte(fout,127);
WriteData(fout,data,128);
len -= 128;
data += 128;
}
if (len > 0)
{
WriteByte(fout,len-1);
WriteData(fout,data,len);
data += len;
}
}
ob = *data;
}
/* if (WriteSize-pos & 1)
WriteByte(fout,0); */
#else
WriteData(fout,data,size);
#endif
}
int main(argc,argv)
int argc;
char *argv[];
{
FILE *fin,*fout;
int x,y,n,b;
int AllRows,oldperc,newperc;
UBYTE *ptr;
if (argc == 3)
{
fin = fopen(argv[1],"r");
if (fin)
{
if (fread((char *)&PCXHeader,1,128,fin) == 128)
{
PCXWide = SwapWord(PCXHeader.x2)+1;
PCXHigh = SwapWord(PCXHeader.y2)+1;
PCXWide -= SwapWord(PCXHeader.x1);
PCXHigh -= SwapWord(PCXHeader.y1);
SwapWord(PCXHeader.hres);
SwapWord(PCXHeader.vres);
PCX_BPL = SwapWord(PCXHeader.bpl);
IFF_BPL = PCX_BPL;
if (IFF_BPL & 1)
IFF_BPL++;
PCXDeep = PCXHeader.nplanes;
printf ("Converting %dx%dx%d from PCX to IFF... ",PCXWide,PCXHigh,PCXDeep);
fout = fopen(argv[2],"w");
if (fout)
{
WriteSize = 0;
WriteData(fout,"FORM ILBMBMHD",16);
WriteLong(fout,20);
WriteWord(fout,PCXWide); /* Width */
WriteWord(fout,PCXHigh); /* Height */
WriteWord(fout,PCXHeader.x1); /* Xoffset */
WriteWord(fout,PCXHeader.y1); /* Yoffset */
WriteByte(fout,PCXDeep); /* Depth */
WriteByte(fout,0); /* Masking */
#ifdef COMPRESS
WriteByte(fout,1); /* Compression on */
#else
WriteByte(fout,0); /* Compression off */
#endif
WriteByte(fout,0); /* pad */
WriteWord(fout,0); /* Transparent Color */
WriteByte(fout,10); /* XAspect, YAspect */
WriteByte(fout,PCXHeader.hres*10 / PCXHeader.vres);
WriteWord(fout,PCXWide); /* PageWidth */
WriteWord(fout,PCXHigh); /* PageHeight */
WriteData(fout,"CMAP",4);
WriteLong(fout,(1<<PCXDeep)*3);
WriteData(fout,&PCXHeader.triple,(1<<PCXDeep)*3);
WriteData(fout,"BODY ",8);
BodyPosition = WriteSize-4;
AllRows = PCXHigh*PCXDeep;
n = 0;
ptr = Buffer;
oldperc = -1;
for (y=0; y<AllRows; y++)
{
newperc = (y*100)/AllRows;
if (newperc != oldperc)
printf ("%3d%%\b\b\b\b",newperc);
oldperc = newperc;
for (x=n; x<PCX_BPL; x+=n)
{
n = ReadByte(fin);
if ((n & 0xC0) == 0xC0)
{
n &= 0x3F;
b = ReadByte(fin);
memset(ptr,b,n);
ptr += n;
}
else
{
*ptr++ = n;
n = 1;
}
}
WriteIFFRow(fout,Buffer,IFF_BPL);
ptr = Buffer;
n = x-PCX_BPL;
if (n > 0)
{
memset(ptr,b,n);
ptr += n;
}
}
BodySize = WriteSize - BodyPosition - 4;
if (BodySize & 1)
{
WriteByte(fout,0);
BodySize++;
}
fseek(fout,BodyPosition,0);
WriteLong(fout,BodySize);
fseek(fout,4,0);
WriteLong(fout,BodyPosition+BodySize-4);
printf ("Done!\n");
return 0;
}
else
printf ("%%%% Unable to open %s for output as IFF file\n",argv[2]);
}
else
printf ("%%%% Invalid PCX file\n");
}
else
printf ("%%%% Unable to open %s for input from PCX file\n",argv[1]);
}
else
printf ("\nUsage:\n\n PCXTOIFF <sourcepcxfile> <destifffile>\n\n");
return 20;
}